package com.fcmeditech.AsianSexyGirls.File;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import com.fcmeditech.AsianSexyGirls.File.ImageDownloader.FlushedInputStream;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Handler;
import android.os.Message;	
import android.util.Log;
import android.widget.ImageView;

public class BitmapManager2 {
	
	//INSTANCE;  
	private final Map<String, SoftReference<Bitmap>> cache;  
    private final ExecutorService pool;  
    private Map<ImageView, String> imageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());  
    private Bitmap placeholder;  
    
 //--------------Constructor 
    public BitmapManager2() {  
        cache = new HashMap<String, SoftReference<Bitmap>>();  //--->create a cache 
        pool = Executors.newFixedThreadPool(5);//--->create 5 thread  
    }  
    public BitmapManager2(int threadNumber) {  
        cache = new HashMap<String, SoftReference<Bitmap>>();  //--->create a cache 
        pool = Executors.newFixedThreadPool(threadNumber);//--->create 5 thread  
    }  
    public void setPlaceholder(Bitmap bmp) {  
        placeholder = bmp;  
    }  
  //------------getBitmapFromCache-----------------
    public Bitmap getBitmapFromCache(String url,int position) {  
        if (cache.containsKey(url)) {  
        	//Log.d(null, "position : "+ position +"--get Bitmap OK--" + url); 
            return cache.get(url).get();  
        }  
  
        return null;  
    }  
 //----------- 
    public void queueJob(final String url, final ImageView imageView,  
            final int width, final int height, final int position) {  
        /* Create handler in UI thread. */  
      /**
       * Handler method() is used to recieved message from a Handler in Thread
       */
    	final Handler handler = new Handler() {  
            @Override  
            public void handleMessage(Message msg) {  
                String tag = imageViews.get(imageView);//--->GET url OF imageView in Map<>  
                if (tag != null && tag.equals(url))
                   {  
                    if (msg.obj != null) {  
                    	//FOR TEST
                        
                        Thread current=Thread.currentThread();
                    	String threadname =current.getName();
                    	int priority=current.getPriority();
                    	
                        imageView.setImageBitmap((Bitmap)msg.obj); //--->Receive msg.obj from Handler in pool.submit(Runable ) belows.
                        Log.d(null,position + " -receive message in Thread:  "+threadname);
                    } else {  
                        imageView.setImageBitmap(placeholder);  
                        Log.d(null,"position "+ position + "--fail " + url);  
                    }  
                }  
            }  
        };  
        //---Submits a Runnable task for execution and returns a Future representing that task. The Future's get method will return null upon successful completion.
        pool.submit(new Runnable() {  
            @Override  
            public void run() {  
                Bitmap bmp=null;
                Bitmap bmp2=null;
                long loadtime=System.currentTimeMillis();
				try {
				//	bmp = getbitmapFromUrl(url, width, height);//--->download Image from URL,return a Bitmap
					
					bmp2= getbitmapFromUrl2(url);
					//rotate image if height<width
					//option:
					
					bmp=rotate90(bmp2);
					
					
					//end option
				} catch (MalformedURLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}  
				//-----------Create a message to send to HandlerMessage------------------------------
                Message message = Message.obtain(); //--->create a new message 
                message.obj = bmp;  //--->set object of message =bmp;
                //FOR TEST
                loadtime=System.currentTimeMillis()-loadtime;
                Thread current=Thread.currentThread();
            	String threadname =current.getName();
            	int priority=current.getPriority();
            	
                Log.d(null,position+ " Download & Send message " + " Time: "+ loadtime +" Thread: " +threadname+ " Priority: "+priority);  
               
                handler.sendMessage(message);  //--->Pushes a message onto the end of the message queue after all pending messages before the current time.
                //It will be received in handleMessage, in the thread attached to this handler.


            }  
        });  
    }  
  //--------------------Load Bitmap from Cache-------------------------------------------------------
    public void loadBitmap(final String url, final ImageView imageView,final int width, final int height,final int position) {  
        imageViews.put(imageView, url);  //--->put imageView and Its URL to MAP<>
        
        Bitmap bitmap = getBitmapFromCache(url,position);  //--->getBitMap from Cache
         // check in UI thread, so no concurrency issues  
        if (bitmap != null) {  
        	
        	Thread current=Thread.currentThread();
        	String threadname =current.getName();
        	int priority=current.getPriority();
        	
            Log.d(null,position+ " Get & Set: Image "+  " Thread: " +threadname+ " Priority: "+priority);  
            imageView.setImageBitmap(bitmap);  
        } else {  
            //imageView.setImageBitmap(placeholder);  
            queueJob(url, imageView, width, height,position);//---> If there is no Bitmap in Cache--->download it from URL
        }  
    }  
  //---------------------------Download Bitmap from URL-----------
    private Bitmap downloadBitmap(String url, int width, int height) {  
        try {  
            Bitmap bitmap = BitmapFactory.decodeStream((InputStream) new URL(url).getContent());  //--->download Bitmap from URL
            bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);  
            cache.put(url, new SoftReference<Bitmap>(bitmap));  //---put Bitmap and its URL to cache.
            return bitmap;  
        } catch (MalformedURLException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
  
        return null;  
    }  
//------------------------------------
    public  Bitmap getbitmapFromUrl(final String urlString,final int width,final int height) throws MalformedURLException, IOException {
    	URL url = new URL(urlString);
        HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
        InputStream in = urlConnection.getInputStream();
        Bitmap bitmap = BitmapFactory.decodeStream(in);
        bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);  
        cache.put(urlString, new SoftReference<Bitmap>(bitmap));
        urlConnection.disconnect();
        return(bitmap);
    }
  //------------------------------------
    public  Bitmap getbitmapFromUrl2(final String urlString) throws MalformedURLException, IOException {
    	/*URL url = new URL(urlString);
        HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
        InputStream in = urlConnection.getInputStream();
        Bitmap bitmap = BitmapFactory.decodeStream(new FlushedInputStream(in));
        //   bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);  
        cache.put(urlString, new SoftReference<Bitmap>(bitmap));
        urlConnection.disconnect();
        return(bitmap);*/
    	final HttpClient hc=new DefaultHttpClient();
		final HttpGet hg=new HttpGet(urlString);
		try{
    		//connect server get stream
    		HttpResponse hr=hc.execute(hg);
    		final int statusCode = hr.getStatusLine().getStatusCode();
    		if (statusCode != HttpStatus.SC_OK) { 
    	            //Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + urlString); 
    	            return null;
    	        }
    		final HttpEntity he=hr.getEntity();
    		if (he != null) {
                InputStream is = null;
                try {
                    is = he.getContent(); 
                    final Bitmap bitmap =BitmapFactory.decodeStream(new FlushedInputStream(is));
                    
                    if(bitmap==null){ Log.d(null,"decode is fail--lehuy");}
                    
                    cache.put(urlString, new SoftReference<Bitmap>(bitmap));
             
                    return bitmap;
                } finally {
                    if (is != null) {
                        is.close();  
                    }
                    he.consumeContent();
                }
            }
		}
		catch (Exception e) {
			// Could provide a more explicit error message for IOException or IllegalStateException
	        hg.abort();
	        //Log.w("ImageDownloader", "Error while retrieving bitmap from " + urlString);
		}
		return null;
    		
    }
    
    private Bitmap rotate90(Bitmap img)
    {
    	//long loadtime=System.currentTimeMillis();
    	int height=img.getHeight();
        int width=img.getWidth();
        if(height<width){
        	Matrix mat=new Matrix();
        	mat.preRotate(90);
        	return Bitmap.createBitmap(img, 0, 0, width, height, mat, true);
        }
        //loadtime=System.currentTimeMillis()-loadtime;
        //Log.d(null,"Time to rotate: "+loadtime);
        return img;
    }
    static class FlushedInputStream extends FilterInputStream {
	    public FlushedInputStream(InputStream inputStream) {
	        super(inputStream);
	    }

	    @Override
	    public long skip(long n) throws IOException {
	        long totalBytesSkipped = 0L;
	        while (totalBytesSkipped < n) {
	            long bytesSkipped = in.skip(n - totalBytesSkipped);
	            if (bytesSkipped == 0L) {
	                  int bytetemp = read();
	                  if (bytetemp < 0) {
	                      break;  // we reached EOF
	                  } else {
	                      bytesSkipped = 1; // we read one byte
	                  }
	           }
	            totalBytesSkipped += bytesSkipped;
	        }
	        return totalBytesSkipped;
	    }
	}
}
